/*
 * Copyright (c) 2025 Li Auto Inc. and its affiliates
 * Licensed under the Apache License, Version 2.0(the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "cantrcv_tja1145.h"
#include "cantrcv_tja1145_pbcfg.h"
#include "SchM_CanTrcv1145.h"
#include "Compiler.h"
#if (CONFIG_MODULE_CANIF == 1)
#include "canif_cfg.h"
#include "canif_cbk.h"
#include "canif.h"
#endif
#include "Spi.h"
#if (CONFIG_SERVM_ECUM == 1)
#include "sysm_init.h"
#endif
#include <stdio.h>
#include "Std_Types.h"

#define CANTRCV1145_START_SEC_PRIVATE_BSS
#include "cantrcv1145_memmap.h"
#define CANTRCV1145_BUFFER_SIZE 64u
VAR(uint8, CANTRCV1145_PRIVATE_BSS) tja1145_tx_buf[CANTRCV1145_BUFFER_SIZE];
VAR(uint8, CANTRCV1145_PRIVATE_BSS) tja1145_rx_buf[CANTRCV1145_BUFFER_SIZE];
#define CANTRCV1145_STOP_SEC_PRIVATE_BSS
#include "cantrcv1145_memmap.h"
#define VAR_ALIGN(v, size) __attribute__((aligned(size))) v
#define CANTRCV1145_DET_REPORT(apiId, errId)
#define CANTRCV_ECS_WPE                       0x08u
#define CANTRCV_TES_CW                        0x01u
#define CANTRCV_IS_REQ_NONE                   0x00u
#define CANTRCV_REQ_OP_MODE_MASK              0x0Fu
#define CANTRCV_REQ_OP_MODE_NORMAL            0x01u
#define CANTRCV_REQ_OP_MODE_STANDBY           0x02u
#define CANTRCV_REQ_OP_MODE_SLEEP             0x04u
#define CANTRCV_REQ_CBV_BY_BUS_FLAG           0x40u
#define CANTRCV_STATE_WK_IS_BUS(status_flg)  ((((status_flg).trcv_evt_status & CANTRCV_TES_CW) != 0x00u))
#define CANTRCV_STATE_WK_IS_PIN(status_flg)  ((((status_flg).evt_cap_status & CANTRCV_ECS_WPE) != 0x00u))
#define CANTRCV1145_CLEAR_PO_EVENT_BIT0      (0x61U << 1U | 0x0U)
#define CANTRCV1145_CLEAR_PO_EVENT_BIT1      (0x1U << 4U)
#define CANTRCV1145_ENABLE_WAKEUP_PIN_RISING_EDGE_BIT0      (0x4CU << 1U | 0x0U)
#define CANTRCV1145_ENABLE_WAKEUP_PIN_RISING_EDGE_BIT1      (0x1U)
#define CANTRCV1145_ENABLE_CAN_WAKEUP_BIT0       (0x23U << 1U | 0x0U)
#define CANTRCV1145_ENABLE_CAN_WAKEUP_BIT1       (0x1U)
#define CANTRCV1145_ENTER_SLEEP_MODE_BIT0        (0x1U << 1U | 0x0U)
#define CANTRCV1145_ENTER_SLEEP_MODE_BIT1        (0x1U)
#define CANTRCV1145_WRITE_MC_TO_NORMAL_BIT0      (0x1U << 1U | 0x0U)
#define CANTRCV1145_WRITE_MC_TO_NORMAL_BIT1      (0x7U)
#define CANTRCV1145_READ_MC_BIT0                 (0x1U << 1U | 0x1U)
#define CANTRCV1145_READ_MC_BIT1                 (0x0U)

#define CANTRCV1145_START_SEC_CODE
#include "cantrcv1145_memmap.h"
FUNC(void, CANTRCV1145_CODE) cantrcv_tja1145_clear_po_event(void)
{
	tja1145_tx_buf[0] = CANTRCV1145_CLEAR_PO_EVENT_BIT0;
	tja1145_tx_buf[1] = CANTRCV1145_CLEAR_PO_EVENT_BIT1;

	Std_ReturnType ret = Spi_SetupEB(SpiConf_SpiChannel_SpiChannel_1, (void *)&tja1145_tx_buf[0], NULL, 2);

	if (ret != E_OK)
	{
		return;
	}

	if (Spi_SyncTransmit(SpiConf_SpiJob_SpiJob_1) != E_OK)
	{
		return;
	}
}

FUNC(void, CANTRCV1145_CODE) cantrcv_tja1145_enable_wk_pin_rising_edge(void)
{
	tja1145_tx_buf[0] = CANTRCV1145_ENABLE_WAKEUP_PIN_RISING_EDGE_BIT0;
	tja1145_tx_buf[1] = CANTRCV1145_ENABLE_WAKEUP_PIN_RISING_EDGE_BIT1;

	Std_ReturnType ret = Spi_SetupEB(SpiConf_SpiChannel_SpiChannel_1, (void *)&tja1145_tx_buf[0], NULL, 2);

	if (ret != E_OK)
	{
		return;
	}

	if (Spi_SyncTransmit(SpiConf_SpiJob_SpiJob_1) != E_OK)
	{
		return;
	}
}

FUNC(void, CANTRCV1145_CODE) cantrcv_tja1145_get_status_flags_indication(uint8 cantrcv_idx)
{
	SchM_Enter_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
	cantrcv_prob[cantrcv_idx].status_flg.evt_cap_status = CANTRCV_ECS_WPE;
	SchM_Exit_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
}

FUNC(void, CANTRCV1145_CODE) cantrcv_tja1145_enable_can_wakeup(void)
{
	tja1145_tx_buf[0] = CANTRCV1145_ENABLE_CAN_WAKEUP_BIT0;
	tja1145_tx_buf[1] = CANTRCV1145_ENABLE_CAN_WAKEUP_BIT1;

	Std_ReturnType ret = Spi_SetupEB(SpiConf_SpiChannel_SpiChannel_1, (void *)&tja1145_tx_buf[0], NULL, 2);

	if (ret != E_OK)
	{
		return;
	}

	if (Spi_SyncTransmit(SpiConf_SpiJob_SpiJob_1) != E_OK)
	{
		return;
	}
	cantrcv_tja1145_get_status_flags_indication(0);
}

FUNC(void, CANTRCV1145_CODE) cantrcv_tja1145_enter_sleep_mode(void)
{
	tja1145_tx_buf[0] = CANTRCV1145_ENTER_SLEEP_MODE_BIT0;
	tja1145_tx_buf[1] = CANTRCV1145_ENTER_SLEEP_MODE_BIT1;

	Std_ReturnType ret = Spi_SetupEB(SpiConf_SpiChannel_SpiChannel_1, (void *)&tja1145_tx_buf[0], NULL, 2);

	if (ret != E_OK)
	{
		return;
	}

	if (Spi_SyncTransmit(SpiConf_SpiJob_SpiJob_1) != E_OK)
	{
		return;
	}
}

FUNC(void, CANTRCV1145_CODE) cantrcv_tja1145_init(const cantrcv_cfg_t *cfg_ptr)
{
	Std_ReturnType ret;

	Spi_Init(Spi_Config);
	cantrcv_tja1145_clear_po_event();
	tja1145_tx_buf[0] = CANTRCV1145_WRITE_MC_TO_NORMAL_BIT0;
	tja1145_tx_buf[1] = CANTRCV1145_WRITE_MC_TO_NORMAL_BIT1;

	ret = Spi_SetupEB(SpiConf_SpiChannel_SpiChannel_1, (void *)&tja1145_tx_buf[0], NULL, 2);

	if (ret != E_OK) {
		return;
	}

	ret = Spi_SyncTransmit(SpiConf_SpiJob_SpiJob_1);
	if (ret != E_OK) {
		return;
	}

	tja1145_tx_buf[0] = CANTRCV1145_READ_MC_BIT0;
	tja1145_tx_buf[1] = CANTRCV1145_READ_MC_BIT1;

	ret = Spi_SetupEB(SpiConf_SpiChannel_SpiChannel_1, (void *)&tja1145_tx_buf[0], (void *)&tja1145_rx_buf[0], 2);
	if (ret != E_OK) {
		return;
	}

	ret = Spi_SyncTransmit(SpiConf_SpiJob_SpiJob_1);
	if (ret != E_OK) {
		return;
	}

	cantrcv_tja1145_enable_wk_pin_rising_edge();
	cantrcv_tja1145_enable_can_wakeup();

	for(uint8 index = 0; index < CANTRCV_TJA1145_MAX_CHANNEL; ++index) {
		cantrcv_prob[index].is_init = CANTRCV_TJA1145_IS_INIT;
		cantrcv_prob[index].wk_report = CANTRCV_TJA1145_WU_ENABLE;
		cantrcv_prob[index].wk_reason = CANTRCV_TJA1145_WU_ERROR;
		cantrcv_prob[index].now_op_mode = CanTrcv_Tja1145_ChannelInitState[index];
	}

	cantrcv_is_init = CANTRCV_TJA1145_IS_INIT;
}

FUNC(Std_ReturnType, CANTRCV1145_CODE) cantrcv_tja1145_op_mode_set(uint8 cantrcv_idx, CanTrcv_TrcvModeType op_mode)
{
	Std_ReturnType ret_val = E_NOT_OK;
	canif_tja1145_trcv_mode_indication(cantrcv_idx, op_mode);

	if (op_mode == CANTRCV_TJA1145_OP_MODE_SLEEP) {
		cantrcv_prob[cantrcv_idx].now_op_mode = CANTRCV_TJA1145_OP_MODE_SLEEP;
		canif_tja1145_trcv_mode_indication(cantrcv_idx, CANTRCV_TJA1145_OP_MODE_SLEEP);
		cantrcv_tja1145_enter_sleep_mode();
		return E_OK;
	}

	switch(op_mode) {
		case CANTRCV_TJA1145_OP_MODE_NORMAL:
			if(cantrcv_prob[cantrcv_idx].wk_reason == CANTRCV_TJA1145_WU_ERROR) {
				cantrcv_prob[cantrcv_idx].wk_reason = CANTRCV_TJA1145_WU_INTERNALLY;
			}
			SchM_Enter_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
			cantrcv_prob[cantrcv_idx].req_stat &=  (~((uint32)CANTRCV_REQ_OP_MODE_MASK));
			cantrcv_prob[cantrcv_idx].req_stat |= CANTRCV_REQ_OP_MODE_NORMAL;
			cantrcv_prob[cantrcv_idx].now_op_mode = CANTRCV_TJA1145_OP_MODE_NORMAL;
			ret_val = E_OK;
			SchM_Exit_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
			break;
		case CANTRCV_TJA1145_OP_MODE_STANDBY:
			SchM_Enter_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
			cantrcv_prob[cantrcv_idx].wk_reason = CANTRCV_TJA1145_WU_ERROR;
			cantrcv_prob[cantrcv_idx].req_stat &=  (~((uint32)CANTRCV_REQ_OP_MODE_MASK));
			cantrcv_prob[cantrcv_idx].req_stat |= CANTRCV_REQ_OP_MODE_STANDBY;
			cantrcv_prob[cantrcv_idx].now_op_mode = CANTRCV_TJA1145_OP_MODE_STANDBY;
			ret_val = E_OK;
			SchM_Exit_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
			break;
		case CANTRCV_TJA1145_OP_MODE_SLEEP:
			SchM_Enter_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
			cantrcv_prob[cantrcv_idx].req_stat &=  (~((uint32)CANTRCV_REQ_OP_MODE_MASK));
			cantrcv_prob[cantrcv_idx].req_stat |= CANTRCV_REQ_OP_MODE_SLEEP;
			cantrcv_prob[cantrcv_idx].now_op_mode = CANTRCV_TJA1145_OP_MODE_SLEEP;
			cantrcv_tja1145_enter_sleep_mode();
			ret_val = E_OK;
			SchM_Exit_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
			break;
		default:
			CANTRCV1145_DET_REPORT(CANTRCV_TJA1145_SETOPMODE_ID, CANTRCV_TJA1145_E_PARAM_TRCV_OP_MODE);
			break;
		}
	return ret_val;
}

FUNC(Std_ReturnType, CANTRCV1145_CODE) cantrcv_tja1145_op_mode_get(uint8 cantrcv_idx, CanTrcv_TrcvModeType *op_mode)
{
	*op_mode = cantrcv_prob[cantrcv_idx].now_op_mode;
	return E_OK;
}

FUNC(Std_ReturnType, CANTRCV1145_CODE) cantrcv_tja1145_bus_wk_reason_get(uint8 cantrcv_idx,
	CanTrcv_TrcvWakeupReasonType *wk_reason)
{
#if (CANTRCV_GENERAL_WK_EN != CANTRCV_TJA1145_WAKEUP_NONE)
	*wk_reason = cantrcv_prob[cantrcv_idx].wk_reason;
#else
	*wk_reason = CANTRCV_TJA1145_WU_NOT_SUPPORTED;
#endif
	return E_OK;
}

FUNC(void, CANTRCV1145_CODE) cantrcv_tja1145_wk_report(uint8 cantrcv_idx)
{
	CanTrcv_TrcvWakeupReasonType wuReason = cantrcv_prob[cantrcv_idx].wk_reason;

	switch(wuReason) {
		case CANTRCV_TJA1145_WU_POWER_ON:
#if (CANTRCV_TJA1145_USE_EXTENDED_WU_SRC == STD_ON)
#if (CONFIG_SERVM_ECUM == 1)
			ecum_set_wakeup_event(CanTrcv_Tja1145_GetWuSrcPor(cantrcv_idx));
#endif
			break;
#endif
		case CANTRCV_WK_BY_BUS:
		case CANTRCV_WK_BY_PIN:
#if (CONFIG_SERVM_ECUM == 1)
			ecum_set_wakeup_event(CanTrcv_Tja1145_GetWakeupSource(cantrcv_idx));
#endif
			break;
		default:
			break;
	}
}

FUNC(Std_ReturnType, CANTRCV1145_CODE) cantrcv_tja1145_wk_mode_set(uint8 cantrcv_idx,
	CanTrcv_TrcvWakeupModeType trcv_wk_mode)
{
	Std_ReturnType ret_val = E_NOT_OK;

#if (CANTRCV_GENERAL_WK_EN != CANTRCV_TJA1145_WAKEUP_NONE)
	if (CANTRCV_TJA1145_WU_ENABLE == trcv_wk_mode) {
		cantrcv_prob[cantrcv_idx].wk_report = CANTRCV_TJA1145_WU_ENABLE;
		cantrcv_tja1145_wk_report(cantrcv_idx);
		ret_val = E_OK;
	} else if (CANTRCV_TJA1145_WU_DISABLE == trcv_wk_mode) {
		cantrcv_prob[cantrcv_idx].wk_report = CANTRCV_TJA1145_WU_DISABLE;
		ret_val = E_OK;
	} else if (CANTRCV_TJA1145_WU_CLEAR == trcv_wk_mode) {
		cantrcv_prob[cantrcv_idx].wk_reason = CANTRCV_TJA1145_WU_ERROR;
		ret_val = E_OK;
	} else {
		CANTRCV1145_DET_REPORT(CANTRCV_TJA1145_SETWAKEUPMODE_ID, CANTRCV_TJA1145_E_PARAM_TRCV_WAKEUP_MODE);
	}
#endif

	return ret_val;
}

FUNC(Std_ReturnType, CANTRCV1145_CODE) cantrcv_tja1145_wk_check(uint8 cantrcv_idx)
{
	Std_ReturnType ret_val = E_NOT_OK;

	if(CanTrcv_Tja1145_IsWakeupByBusUsed(cantrcv_idx) &&
	(cantrcv_prob[cantrcv_idx].wk_report == CANTRCV_TJA1145_WU_ENABLE)) {
		SchM_Enter_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
		if (cantrcv_prob[cantrcv_idx].wk_reason == CANTRCV_WK_BY_PIN ||
			cantrcv_prob[cantrcv_idx].wk_reason == CANTRCV_WK_BY_BUS) {
			cantrcv_tja1145_wk_report(cantrcv_idx);
			ret_val = E_OK;
		} else {
			cantrcv_prob[cantrcv_idx].req_stat |= CANTRCV_REQ_CBV_BY_BUS_FLAG;
			if (cantrcv_prob[cantrcv_idx].wk_reason == CANTRCV_WK_BY_PIN ||
				cantrcv_prob[cantrcv_idx].wk_reason == CANTRCV_WK_BY_BUS) {
				ret_val = E_OK;
			} else {
				ret_val = E_NOT_OK;
			}
		}
		SchM_Exit_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
	}

	return ret_val;
}

FUNC(Std_ReturnType, CANTRCV1145_CODE) cantrcv_tja1145_wk_flag_clear(uint8 cantrcv_idx)
{
	return E_OK;
}

FUNC(Std_ReturnType, CANTRCV1145_CODE) cantrcv_tja1145_wk_flag_check(uint8 cantrcv_idx)
{
	return E_OK;
}

FUNC(void, CANTRCV1145_CODE) CanTrcv_Tja1145_MainFunction(void)
{
	for(uint8 index = 0; index < CANTRCV_TJA1145_MAX_CHANNEL; ++index) {
		if (FALSE == CanTrcv_Tja1145_IsChannelUsed(index)) {
			continue;
		}
		if (CANTRCV_TJA1145_IS_INIT != cantrcv_prob[index].is_init){
			return;
		}
		if (CANTRCV_TJA1145_OP_MODE_NORMAL == cantrcv_prob[index].now_op_mode){
			return;
		}

#if (CANTRCV_GENERAL_WK_EN == CANTRCV_TJA1145_WAKEUP_BY_POLLING)
		if ((CanTrcv_Tja1145_IsWakeupByBusUsed(index)) &&
		(cantrcv_prob[index].req_stat != CANTRCV_IS_REQ_NONE)) {

			SchM_Enter_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
			if (CANTRCV_STATE_WK_IS_BUS(cantrcv_prob[index].status_flg)) {
				cantrcv_prob[index].wk_reason = CANTRCV_WK_BY_BUS;
				if (cantrcv_prob[index].wk_report == CANTRCV_TJA1145_WU_ENABLE) {
#if (CONFIG_SERVM_ECUM == 1)
					ecum_check_wakeup(CanTrcv_Tja1145_GetWakeupSource(index));
#endif
				}
			} else if (CANTRCV_STATE_WK_IS_PIN(cantrcv_prob[index].status_flg)) {
				cantrcv_prob[index].wk_reason = CANTRCV_WK_BY_PIN;
				if (cantrcv_prob[index].wk_report == CANTRCV_TJA1145_WU_ENABLE) {
#if (CONFIG_SERVM_ECUM == 1)
					ecum_check_wakeup(CanTrcv_Tja1145_GetWakeupSource(index));
#endif
				}
			} else {
				/* Do nothing */
			}
			SchM_Exit_CANTRCV_TJA1145_EXCLUSIVE_AREA_0();
		}
#endif
	}
}

#define CANTRCV1145_STOP_SEC_CODE
#include "cantrcv1145_memmap.h"
